package com.abel.bigwater.dataserver.model.kming

import com.abel.bigwater.data.BcdString
import com.alibaba.fastjson.JSON
import io.netty.buffer.Unpooled
import org.joda.time.DateTime
import org.junit.Assert.*
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
import org.slf4j.LoggerFactory

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class KmingPacketTest {
    @Test
    fun test11PacketWithHeart() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            deviceStatus.lowVoltMeter20 = true
            limitStatus.upperLimitWarn20 = true

            sessionStatus.serialNo = 102

            data = TermHeartData().also { it.startTime = DateTime(2018, 1, 2, 3, 4, 5).toDate() }
            dataLen = data!!.bufLength()
        }

        val buf = Unpooled.buffer()
        p1.pack(buf)

        val hs = BcdString.hexString(buf, withBlank = true)
        lgr.info("packet with heart: {}", hs)
        assertEquals("aa 96 4c 6d 05 06 07 08 00 01 00 01 00 66 00 00 07 14 18 01 02 03 04 05 2e a0 55 69 ", hs)
    }

    @Test
    fun test12PacketHeartParsing() {
        val buf = Unpooled.buffer().writeBytes(
                BcdString.toByteArray("aa 96 4c 6d 05 06 07 08 00 01 00 01 00 66 00 00 07 14 18 01 02 03 04 05 2e a0 55 69"))
        val p1 = KmingPacket()
        assertTrue(p1.parseBuf(buf))

        lgr.info("json for packet with heart: {}", JSON.toJSONString(p1, true))
        assertTrue(p1.dataLen == 7)
        assertTrue(p1.data is TermHeartData)
        assertEquals(DateTime(2018, 1, 2, 3, 4, 5).toDate(),
                (p1.data as TermHeartData).startTime)

        assertTrue(p1.deviceStatus.lowVoltMeter20)
        assertFalse(p1.deviceStatus.converterFault26)

        assertTrue(p1.limitStatus.upperLimitWarn20)
        assertFalse(p1.limitStatus.zeroWarn24)
    }

    @Test
    fun test13PacketHeartSecret() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            deviceStatus.lowVoltMeter20 = true
            limitStatus.upperLimitWarn20 = true

            sessionStatus.encrypted = true
            sessionStatus.serialNo = 102

            data = TermHeartData().also { it.startTime = DateTime(2018, 1, 2, 3, 4, 5).toDate() }
            dataLen = data!!.bufLength()
        }

        val buf = Unpooled.buffer()
        p1.pack(buf)

        lgr.info("packet with secret heart: {}", BcdString.hexString(buf, withBlank = true))
    }

    @Test
    fun test14PacketHeartSecretParsing() {
        val ba = BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 80 66 00 00 11 14 09 bd 9b 90 d1 99 4a 5a c2 60 08 6f 0c a8
d0 1b 23 99 55 69""")
        val buf = Unpooled.buffer().writeBytes(ba)
        val p1 = KmingPacket()
        assertTrue(p1.parseBuf(buf))

        lgr.info("json for packet with heart: {}", JSON.toJSONString(p1, true))
        assertTrue(p1.dataLen == 17)
        assertTrue(p1.data is TermHeartData)
        assertEquals(DateTime(2018, 1, 2, 3, 4, 5).toDate(),
                (p1.data as TermHeartData).startTime)

        assertTrue(p1.deviceStatus.lowVoltMeter20)
        assertFalse(p1.deviceStatus.converterFault26)

        assertTrue(p1.limitStatus.upperLimitWarn20)
        assertFalse(p1.limitStatus.zeroWarn24)
    }

    @Test
    fun test21PacketShutdownPack() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            deviceStatus.lowVoltMeter20 = true
            limitStatus.upperLimitWarn20 = true

            sessionStatus.serialNo = 102

            data = TermShutdownData()
            dataLen = data!!.bufLength()
        }

        val buf = Unpooled.buffer()
        p1.pack(buf)

        lgr.info("packet with shutdown: {}", BcdString.hexString(buf, withBlank = true))
        assertArrayEquals(BcdString.toByteArray("aa 96 4c 6d 05 06 07 08 00 01 00 01 00 66 00 00 01 15 27 60 55 69"),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun test22PacketShutdownParsing() {
        val buf = Unpooled.buffer().writeBytes(
                BcdString.toByteArray("aa 96 4c 6d 05 06 07 08 00 01 00 01 00 66 00 00 01 15 27 60 55 69"))
        val p1 = KmingPacket()
        assertTrue(p1.parseBuf(buf))

        lgr.info("json for packet with heart: {}", JSON.toJSONString(p1, true))
        assertTrue(p1.dataLen == 1)
        assertTrue(p1.data is TermShutdownData)

        assertTrue(p1.deviceStatus.lowVoltMeter20)
        assertFalse(p1.deviceStatus.converterFault26)

        assertTrue(p1.limitStatus.upperLimitWarn20)
        assertFalse(p1.limitStatus.zeroWarn24)
    }

    @Test
    fun test23PacketShutdownPackSecret() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            deviceStatus.lowVoltMeter20 = true
            limitStatus.upperLimitWarn20 = true

            sessionStatus.encrypted = true
            sessionStatus.serialNo = 102

            data = TermShutdownData()
            dataLen = data!!.bufLength()
        }

        val buf = Unpooled.buffer()
        p1.pack(buf)

        lgr.info("packet with shutdown: {}", BcdString.hexString(buf, withBlank = true))
        assertArrayEquals(BcdString.toByteArray("aa 96 4c 6d 05 06 07 08 00 01 00 01 80 66 00 00 01 15 e7 7f 55 69"),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun test24PacketShutdownParsingSecret() {
        val buf = Unpooled.buffer().writeBytes(
                BcdString.toByteArray("aa 96 4c 6d 05 06 07 08 00 01 00 01 80 66 00 00 01 15 e7 7f 55 69"))
        val p1 = KmingPacket()
        assertTrue(p1.parseBuf(buf))

        lgr.info("json for packet with heart: {}", JSON.toJSONString(p1, true))
        assertTrue(p1.dataLen == 1)
        assertTrue(p1.data is TermShutdownData)

        assertTrue(p1.deviceStatus.lowVoltMeter20)
        assertFalse(p1.deviceStatus.converterFault26)

        assertTrue(p1.limitStatus.upperLimitWarn20)
        assertFalse(p1.limitStatus.zeroWarn24)

        assertTrue(p1.sessionStatus.encrypted)
    }

    @Test
    fun test31PacketReqPack() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            deviceStatus.lowVoltMeter20 = true
            limitStatus.upperLimitWarn20 = true

            sessionStatus.serialNo = 102

            data = TermUploadReqData().also {
                it.longitude = 108.1F
                it.latitude = 22.3F
                it.rtuVolt = 620
                it.meterVolt = 711
                it.rssi = 31
                it.channelCount = 1
                it.channelList.add(KmingChannelType.MeterNetInt)
            }
            dataLen = data!!.bufLength()
        }

        val buf = Unpooled.buffer()
        p1.pack(buf)

        lgr.info("packet with upload-req: {}", BcdString.hexString(buf, withBlank = true))
        assertArrayEquals(BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 00 66 00 00 15 11 33 33 d8 42 66 66 b2 41 00 00 00 00 6c 02
c7 02 1f 01 14 14 4b 90 55 69"""),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun test32PacketReqParsing() {
        val buf = Unpooled.buffer().writeBytes(
                BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 00 66 00 00 15 11 33 33 d8 42 66 66 b2 41 00 00 00 00 6c 02
c7 02 1f 01 14 14 4b 90 55 69"""))
        val p1 = KmingPacket()
        assertTrue(p1.parseBuf(buf))

        lgr.info("json for packet with upload-req: {}", JSON.toJSONString(p1, true))
        assertTrue(p1.dataLen == 21)
        assertTrue(p1.data is TermUploadReqData)

        assertTrue(p1.deviceStatus.lowVoltMeter20)
        assertFalse(p1.deviceStatus.converterFault26)

        assertTrue(p1.limitStatus.upperLimitWarn20)
        assertFalse(p1.limitStatus.zeroWarn24)

        val data = p1.data as TermUploadReqData
        assertEquals(108.1F, data.longitude!!, 1.0E-5F)
        assertEquals(22.3F, data.latitude!!, 1.0E-5F)
        assertEquals(620, data.rtuVolt)
        assertEquals(711, data.meterVolt)
        assertEquals(31, data.rssi!!.toInt())
        assertEquals(1, data.channelCount!!.toInt())
        assertEquals(KmingChannelType.MeterNetInt, data.channelList[0])
    }

    @Test
    fun test33PacketReqPackSecret() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            deviceStatus.lowVoltMeter20 = true
            limitStatus.upperLimitWarn20 = true

            sessionStatus.encrypted = true
            sessionStatus.serialNo = 102

            data = TermUploadReqData().also {
                it.longitude = 108.1F
                it.latitude = 22.3F
                it.rtuVolt = 620
                it.meterVolt = 711
                it.rssi = 31
                it.channelCount = 1
                it.channelList.add(KmingChannelType.MeterNetInt)
            }
            dataLen = data!!.bufLength()
        }

        val buf = Unpooled.buffer()
        p1.pack(buf)

        lgr.info("packet with shutdown: {}", BcdString.hexString(buf, withBlank = true))
        assertArrayEquals(BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 80 66 00 00 21 11 52 21 ee f9 45 e1 25 f4 ef d1 c7 a8 bb cd
4a c8 4e dd 77 58 7a af 0c 51 f4 05 a8 2d 2e 13 71 b8 d4 34 55 69"""),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun test34PacketReqParsingSecret() {
        val buf = Unpooled.buffer().writeBytes(
                BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 80 66 00 00 21 11 52 21 ee f9 45 e1 25 f4 ef d1 c7 a8 bb cd
4a c8 4e dd 77 58 7a af 0c 51 f4 05 a8 2d 2e 13 71 b8 d4 34 55 69"""))
        val p1 = KmingPacket()
        assertTrue(p1.parseBuf(buf))

        lgr.info("json for packet with heart: {}", JSON.toJSONString(p1, true))
        assertTrue(p1.dataLen == 0x21)
        assertTrue(p1.data is TermUploadReqData)

        assertTrue(p1.deviceStatus.lowVoltMeter20)
        assertFalse(p1.deviceStatus.converterFault26)

        assertTrue(p1.limitStatus.upperLimitWarn20)
        assertFalse(p1.limitStatus.zeroWarn24)

        assertTrue(p1.sessionStatus.encrypted)

        val data = p1.data as TermUploadReqData
        assertEquals(108.1F, data.longitude!!, 1.0E-5F)
        assertEquals(22.3F, data.latitude!!, 1.0E-5F)
        assertEquals(620, data.rtuVolt)
        assertEquals(711, data.meterVolt)
        assertEquals(31, data.rssi!!.toInt())
        assertEquals(1, data.channelCount!!.toInt())
        assertEquals(KmingChannelType.MeterNetInt, data.channelList[0])
    }

    @Test
    fun test35PacketReqPackStatus() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            sessionStatus.serialNo = 102

            data = TermUploadReqData().also {
                it.longitude = 108.1F
                it.latitude = 22.3F
                it.rtuVolt = 620
                it.meterVolt = 711
                it.rssi = 31
                it.channelCount = 1
                it.channelList.add(KmingChannelType.MeterNetInt)
            }
            dataLen = data!!.bufLength()
        }

        val buf = Unpooled.buffer()
        p1.pack(buf)

        lgr.info("packet with upload-req: {}", BcdString.hexString(buf, withBlank = true))
        assertArrayEquals(BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 00 00 00 00 66 00 00 15 11 33 33 d8 42 66 66 b2 41 00 00 00 00 6c 02
c7 02 1f 01 14 14 c8 ae 55 69"""),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun test36PacketReqPackSecretStatus() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            sessionStatus.encrypted = true
            sessionStatus.serialNo = 102

            data = TermUploadReqData().also {
                it.longitude = 108.1F
                it.latitude = 22.3F
                it.rtuVolt = 620
                it.meterVolt = 711
                it.rssi = 31
                it.channelCount = 1
                it.channelList.add(KmingChannelType.MeterNetInt)
            }
            dataLen = data!!.bufLength()
        }

        val buf = Unpooled.buffer()
        p1.pack(buf)

        lgr.info("packet with upload-req: {}", BcdString.hexString(buf, withBlank = true))
        assertArrayEquals(BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 00 00 00 80 66 00 00 21 11 52 21 ee f9 45 e1 25 f4 ef d1 c7 a8 bb cd
4a c8 4e dd 77 58 7a af 0c 51 f4 05 a8 2d 2e 13 71 b8 c5 3b 55 69"""),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun test41PacketSendPack() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            deviceStatus.lowVoltMeter20 = true
            limitStatus.upperLimitWarn20 = true

            sessionStatus.serialNo = 102

            data = TermSendData().also {
                it.startTime = DateTime(2018, 4, 5, 6, 7, 8).toDate()
                it.sampleSeconds = 600
                it.channelCount = 1
                it.dataCount = 1

                val kcd = KmingChannelData(KmingChannelType.MeterNetInt, arrayListOf(12345), null)
                it.channelDataList.add(kcd)
            }
            dataLen = data!!.bufLength()
        }

        val buf = Unpooled.buffer()
        p1.pack(buf)

        lgr.info("packet with send-data: {}", BcdString.hexString(buf, withBlank = true))
        assertArrayEquals(BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 00 66 00 00 13 12 01 01 18 04 05 06 07 08 58 02 00 00 14 14
00 00 30 39 23 1a 55 69"""),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun test42PacketSendParsing() {
        val buf = Unpooled.buffer().writeBytes(
                BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 00 66 00 00 13 12 01 01 18 04 05 06 07 08 58 02 00 00 14 14
00 00 30 39 23 1a 55 69"""))
        val p1 = KmingPacket()
        assertTrue(p1.parseBuf(buf))

        lgr.info("json for packet with send-data: {}", JSON.toJSONString(p1, true))
        assertTrue(p1.dataLen == 19)
        assertTrue(p1.data is TermSendData)

        assertTrue(p1.deviceStatus.lowVoltMeter20)
        assertFalse(p1.deviceStatus.converterFault26)

        assertTrue(p1.limitStatus.upperLimitWarn20)
        assertFalse(p1.limitStatus.zeroWarn24)

        assertFalse(p1.sessionStatus.encrypted)

        val data = p1.data as TermSendData
        assertEquals(DateTime(2018, 4, 5, 6, 7, 8).toDate(),
                data.startTime)
        assertEquals(600L, data.sampleSeconds)
        assertEquals(1.toShort(), data.channelCount)
        assertEquals(1.toShort(), data.dataCount)
        assertEquals(1, data.channelDataList.size)
        assertEquals(1, data.channelDataList[0].dataList.size)
        assertEquals(12345, data.channelDataList[0].dataList[0])
    }

    @Test
    fun test43PacketSendPackSecret() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            deviceStatus.lowVoltMeter20 = true
            limitStatus.upperLimitWarn20 = true

            sessionStatus.encrypted = true
            sessionStatus.serialNo = 102

            data = TermSendData().also {
                it.startTime = DateTime(2018, 4, 5, 6, 7, 8).toDate()
                it.sampleSeconds = 600
                it.channelCount = 1
                it.dataCount = 1

                val kcd = KmingChannelData(KmingChannelType.MeterNetInt, arrayListOf(12345), null)
                it.channelDataList.add(kcd)
            }
            dataLen = data!!.bufLength()
        }

        val buf = Unpooled.buffer()
        p1.pack(buf)

        lgr.info("packet with send-data: {}", BcdString.hexString(buf, withBlank = true))
        assertArrayEquals(BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 80 66 00 00 21 12 9f 89 5a d0 36 43 74 3d 87 29 5a 05 54 8b
bd 7d ab 82 3b ee d9 6d c1 28 1c 47 95 64 c4 de b0 28 32 dc 55 69  """),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun test44PacketSendParsingSecret() {
        val buf = Unpooled.buffer().writeBytes(
                BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 80 66 00 00 21 12 9f 89 5a d0 36 43 74 3d 87 29 5a 05 54 8b
bd 7d ab 82 3b ee d9 6d c1 28 1c 47 95 64 c4 de b0 28 32 dc 55 69  """))
        val p1 = KmingPacket()
        assertTrue(p1.parseBuf(buf))

        lgr.info("json for packet with heart: {}", JSON.toJSONString(p1, true))
        assertTrue(p1.dataLen == 0x21)
        assertTrue(p1.data is TermSendData)

        assertTrue(p1.deviceStatus.lowVoltMeter20)
        assertFalse(p1.deviceStatus.converterFault26)

        assertTrue(p1.limitStatus.upperLimitWarn20)
        assertFalse(p1.limitStatus.zeroWarn24)

        assertTrue(p1.sessionStatus.encrypted)

        val data = p1.data as TermSendData
        assertEquals(DateTime(2018, 4, 5, 6, 7, 8).toDate(),
                data.startTime)
        assertEquals(600L, data.sampleSeconds)
        assertEquals(1.toShort(), data.channelCount)
        assertEquals(1.toShort(), data.dataCount)
        assertEquals(1, data.channelDataList.size)
        assertEquals(1, data.channelDataList[0].dataList.size)
        assertEquals(12345, data.channelDataList[0].dataList[0])
    }

    @Test
    fun test51PacketBurstPack() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            deviceStatus.lowVoltMeter20 = true
            limitStatus.upperLimitWarn20 = true

            sessionStatus.encrypted = false
            sessionStatus.serialNo = 0xFF

            data = TermBurstData().apply {
                eventCnt = 1
                startTime = DateTime(2011, 2, 3, 4, 5, 6).toDate()
                eventList.add(KmingEvent(KmingChannelType.MeterNetInt,
                        DeviceStatus().also { it.lowVoltMeter20 = true },
                        LimitStatus().also { it.upperLimitWarn20 = true }
                ))
            }
        }

        val buf = Unpooled.buffer().also { p1.pack(it) }

        lgr.info("burst packet: {}", BcdString.hexString(buf, withBlank = true))

        assertArrayEquals(BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 00 ff 00 00 0e 13 01 11 02 03 04 05 06 14 14 00 01 00 01 87
b0 55 69  """),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun test52PacketBurstParsing() {
        val buf = Unpooled.buffer().writeBytes(BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 00 ff 00 00 0e 13 01 11 02 03 04 05 06 14 14 00 01 00 01 87
b0 55 69  """))

        val p1 = KmingPacket()
        assertTrue(p1.parseBuf(buf))
        lgr.info("json for burst packet: {}", JSON.toJSONString(p1, true))

        assertEquals(p1.termCode.fmt, "Lm5060708")

        assertTrue(p1.deviceStatus.lowVoltMeter20)
        assertFalse(p1.deviceStatus.emptyWarn25)

        assertTrue(p1.limitStatus.upperLimitWarn20)
        assertFalse(p1.limitStatus.lowerLimitWarn21)

        assertFalse(p1.sessionStatus.encrypted)
        assertFalse(p1.sessionStatus.hasNext)
        assertEquals(0xFF, p1.sessionStatus.serialNo)

        assertTrue(p1.data is TermBurstData)
        val data = p1.data as TermBurstData

        assertEquals(1.toShort(), data.eventCnt)
        assertEquals(DateTime(2011, 2, 3, 4, 5, 6).toDate(), data.startTime)
        assertEquals(1, data.eventList.size)
        assertEquals(KmingChannelType.MeterNetInt, data.eventList[0].ch)
        assertTrue(data.eventList[0].devStatus.lowVoltMeter20)
        assertTrue(data.eventList[0].lmtStatus.upperLimitWarn20)
    }

    @Test
    fun test53PacketBurstPackSecret() {
        val p1 = KmingPacket().apply {
            termCode.size = SizeType.Horizon100
            termCode.remote = RemoteType.PulseRemote
            termCode.codeBcd = BcdString.fromBcdString("05 06 07 08")

            deviceStatus.lowVoltMeter20 = true
            limitStatus.upperLimitWarn20 = true

            sessionStatus.encrypted = true
            sessionStatus.serialNo = 0xFF

            data = TermBurstData().apply {
                eventCnt = 1
                startTime = DateTime(2011, 2, 3, 4, 5, 6).toDate()
                eventList.add(KmingEvent(KmingChannelType.MeterNetInt,
                        DeviceStatus().also { it.lowVoltMeter20 = true },
                        LimitStatus().also { it.upperLimitWarn20 = true }
                ))
            }
        }

        val buf = Unpooled.buffer().also { p1.pack(it) }

        lgr.info("burst packet: {}", BcdString.hexString(buf, withBlank = true))

        assertArrayEquals(BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 80 ff 00 00 11 13 93 41 ea 37 1b 64 e6 2d d6 25 8d 18 25 92
52 ae 95 03 55 69  """),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun test54PacketBurstParsingSecret() {
        val buf = Unpooled.buffer().writeBytes(BcdString.toByteArray("""aa 96 4c 6d 05 06 07 08 00 01 00 01 80 ff 00 00 11 13 93 41 ea 37 1b 64 e6 2d d6 25 8d 18 25 92
52 ae 95 03 55 69  """))

        val p1 = KmingPacket()
        assertTrue(p1.parseBuf(buf))
        lgr.info("json for burst packet: {}", JSON.toJSONString(p1, true))

        assertEquals(p1.termCode.fmt, "Lm5060708")

        assertTrue(p1.deviceStatus.lowVoltMeter20)
        assertFalse(p1.deviceStatus.emptyWarn25)

        assertTrue(p1.limitStatus.upperLimitWarn20)
        assertFalse(p1.limitStatus.lowerLimitWarn21)

        assertTrue(p1.sessionStatus.encrypted)
        assertFalse(p1.sessionStatus.hasNext)
        assertEquals(0xFF, p1.sessionStatus.serialNo)

        assertTrue(p1.data is TermBurstData)
        val data = p1.data as TermBurstData

        assertEquals(1.toShort(), data.eventCnt)
        assertEquals(DateTime(2011, 2, 3, 4, 5, 6).toDate(), data.startTime)
        assertEquals(1, data.eventList.size)
        assertEquals(KmingChannelType.MeterNetInt, data.eventList[0].ch)
        assertTrue(data.eventList[0].devStatus.lowVoltMeter20)
        assertTrue(data.eventList[0].lmtStatus.upperLimitWarn20)
    }

    @Test
    fun testTermReq() {
        val data = TermUploadReqData().apply {
            longitude = 116.0F
            latitude = 22.0F
            rtuVolt = 720
            meterVolt = 712

            rssi = 30
            channelCount = 1
            channelList.add(KmingChannelType.MeterForwardInt)
        }
        val buf = Unpooled.buffer().apply { data.pack(this) }

        lgr.info("term req: {}", BcdString.hexString(buf, withBlank = true))
        assertArrayEquals(BcdString.toByteArray("11 00 00 e8 42 00 00 b0 41 00 00 00 00 d0 02 c8 02 1e 01 12 14"),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun testSendData() {
        val data = TermSendData().apply {
            channelCount = 1
            dataCount = 1
            startTime = DateTime(2010, 1, 2, 3, 4, 5).toDate()
            sampleSeconds = 600

            val kcd = KmingChannelData(KmingChannelType.MeterForwardInt, arrayListOf(1), null)
            channelDataList.add(kcd)
        }
        val buf = Unpooled.buffer().apply { data.pack(this) }

        lgr.info("term send: {}", BcdString.hexString(buf, withBlank = true))

        assertArrayEquals(BcdString.toByteArray("12 01 01 10 01 02 03 04 05 58 02 00 00 12 14 00 00 00 01"),
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })
    }

    @Test
    fun testTermEvent() {
        val tv = TermBurstData().apply {
            eventCnt = 1
            startTime = DateTime(2010, 1, 2, 3, 4, 5).toDate()
            eventList.add(KmingEvent(KmingChannelType.MeterFlow,
                    DeviceStatus().also { it.sensorFault27 = true },
                    LimitStatus().also { it.zeroWarn24 = true }))
        }
        val buf = Unpooled.buffer().apply {
            tv.pack(this)
        }

        lgr.info("event: {}", BcdString.hexString(buf, withBlank = true))
        assertArrayEquals(BcdString.fromBcdString("13 01 10 01 02 03 04 05 11 13 00 80 00 10").hexArray,
                ByteArray(buf.readableBytes()).also { buf.readBytes(it) })

    }

    @Test
    fun testTermHeart() {
        val data = TermHeartData().apply {
            this.startTime = DateTime(2010, 1, 2, 3, 4, 5).toDate()
        }
        val buf = Unpooled.buffer().apply { data.pack(this) }

        lgr.info("heart: {}", BcdString.hexString(buf))

        assertArrayEquals(byteArrayOf(0x14, 0x10, 1, 2, 3, 4, 5),
                ByteArray(data.bufLength()).also { buf.readBytes(it) })
    }

    @Test
    fun testShurtdown() {
        val data = TermShutdownData()
        val buf = Unpooled.buffer().apply { data.pack(this) }

        lgr.info("heart: {}", BcdString.hexString(buf))

    }

    @Test
    fun testShuwdownResponse() {
        val data = KmingRepondShutdown().apply {
            this.startTime = DateTime(2018, 1, 2, 3, 4, 5).toDate()
            this.sessionReponseType = SessionReponseType.BadCrc
        }
        val buf = Unpooled.buffer().apply { data.pack(this) }

        lgr.info("heart: {}", BcdString.hexString(buf, withBlank = true))

        assertArrayEquals(BcdString.toByteArray("15 18 01 02 03 04 05 03"),
                ByteArray(buf.readableBytes()).apply { buf.readBytes(this) })
    }

    @Test
    fun testResponse() {
        val data = KmingResponseData(KmingDataType.TermUploadReq).apply {
            this.sessionReponseType = SessionReponseType.Success
        }
        val buf = Unpooled.buffer().apply { data.pack(this) }

        lgr.info("response: {}", BcdString.hexString(buf))

        assertArrayEquals(byteArrayOf(0x11, 0x01),
                ByteArray(data.bufLength()).also { buf.readBytes(it) })
    }

    companion object {
        private val lgr = LoggerFactory.getLogger(KmingPacketTest::class.java)
    }
}